<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="keywords" content="EduBot,教育小助手,PPTX,思维导图,知识图谱,自动生成,AI教学,在线转换,思维导图生成器,智能知识体系,教学工具,教学素材,知识提取,课件优化,教学辅助工具,思维训练,高效学习,知识结构化,可视化思维,知识点关联">
    <meta name="description" content="EduBot PPTX转思维导图工具，基于AI技术自动提取PPTX文件中的知识点，生成结构化思维导图，帮助教师优化课件内容，提升教学效果">
    <title>EduBot - PPTX转思维导图</title>
    <link rel="icon" type="image/png" href="static/icons/AiKeTangJiaoXuePingCeXiTong.png">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jsmind@0.8.7/style/jsmind.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/jsmind@0.8.7/es6/jsmind.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jsmind@0.8.7/es6/jsmind.draggable-node.js"></script>
    <script src="{{ url_for('static', filename='javascripts/PptxGeneratesMindMaps.js') }}"></script>
    <style>
        :root {
            --primary-color: #0fe;
            --secondary-color: #01c4ff;
            --accent-color: #ff2a6d;
            --bg-dark: #050819;
            --bg-darker: #02050e;
            --text-light: #f2f2f7;
            --text-bright: #fff;
            --card-bg: rgba(5, 10, 25, 0.85);
            --neon-glow: 0 0 10px rgba(0, 255, 238, 0.7), 0 0 20px rgba(0, 255, 238, 0.4);
            --text-glow: 0 0 5px rgba(0, 255, 238, 0.7);
            --scrollbar-width: 6px;
            --scrollbar-track: rgba(5, 15, 40, 0.5);
            --scrollbar-thumb: rgba(0, 255, 238, 0.3);
            --scrollbar-thumb-hover: rgba(0, 255, 238, 0.6);
            --borders: rgba(0, 255, 238, 0.3);
            --shadow-neon: 0 0 15px rgba(0, 255, 238, 0.3);
        }
        
        ::-webkit-scrollbar {
            width: var(--scrollbar-width);
            height: var(--scrollbar-width);
        }
        
        ::-webkit-scrollbar-track {
            background: var(--scrollbar-track);
            border-radius: 4px;
        }
        
        ::-webkit-scrollbar-thumb {
            background: var(--scrollbar-thumb);
            border-radius: 4px;
            box-shadow: var(--shadow-neon);
            transition: all 0.3s ease;
        }
        
        ::-webkit-scrollbar-thumb:hover {
            background: var(--scrollbar-thumb-hover);
            box-shadow: var(--neon-glow);
        }
        
        ::-webkit-scrollbar-corner {
            background: var(--scrollbar-track);
        }
        
        * {
            scrollbar-width: thin;
            scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
        }
        
        body {
            background: radial-gradient(ellipse at bottom, var(--bg-dark) 0%, var(--bg-darker) 80%);
            color: var(--text-light);
            font-family: 'Segoe UI', sans-serif;
            margin: 0;
            padding: 0;
            min-height: 100vh;
            position: relative;
            overflow-x: hidden;
        }
        
        body::before {
            content: "";
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: 
                url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0h100v100H0z' fill='none'/%3E%3Cpath d='M0 0h1v1H0z' fill='rgba(0,255,238,0.03)'/%3E%3C/svg%3E"),
                radial-gradient(circle at 20% 80%, rgba(0, 255, 238, 0.03) 0%, transparent 20%),
                radial-gradient(circle at 80% 20%, rgba(255, 42, 109, 0.03) 0%, transparent 20%);
            pointer-events: none;
            z-index: -1;
        }
        
        .page-container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            position: relative;
            z-index: 1;
        }
        
        .header {
            text-align: center;
            margin-bottom: 2rem;
            position: relative;
            padding-top: 1rem;
        }
        
        .header h1 {
            font-weight: 700;
            color: var(--text-bright);
            text-shadow: var(--text-glow);
            margin-bottom: 0.5rem;
            font-size: 2rem;
            letter-spacing: 1px;
            position: relative;
            display: inline-block;
        }
        
        .header h1::after {
            content: "";
            position: absolute;
            bottom: -8px;
            left: 50%;
            transform: translateX(-50%);
            width: 60%;
            height: 2px;
            background: linear-gradient(90deg, transparent, var(--primary-color), transparent);
        }
        
        .header p {
            color: rgba(242, 242, 247, 0.8);
            max-width: 600px;
            margin: 0.8rem auto 0;
            font-size: 1rem;
        }
        
        .upload-container {
            background: var(--card-bg);
            border-radius: 14px;
            padding: 1.8rem;
            margin-bottom: 2rem;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
            backdrop-filter: blur(10px);
            border: 1px solid var(--borders);
            max-width: 600px;
            margin-left: auto;
            margin-right: auto;
            transition: all 0.3s ease;
        }
        
        .upload-container:hover {
            box-shadow: var(--shadow-neon);
        }
        
        .upload-area {
            border: 2px dashed var(--borders);
            border-radius: 12px;
            padding: 2rem 1.5rem;
            text-align: center;
            transition: all 0.3s ease;
            cursor: pointer;
            background: rgba(0, 0, 0, 0.2);
        }
        
        .upload-area:hover {
            border-color: var(--primary-color);
            box-shadow: var(--neon-glow);
            transform: translateY(-5px);
        }
        
        .upload-icon {
            font-size: 3rem;
            color: var(--primary-color);
            margin-bottom: 1rem;
            filter: drop-shadow(0 0 8px rgba(0, 255, 238, 0.6));
        }
        
        .btn-primary {
            background: transparent;
            border: 1px solid var(--primary-color);
            color: var(--primary-color);
            padding: 0.5rem 1.5rem;
            border-radius: 50px;
            box-shadow: var(--shadow-neon);
            transition: all 0.3s;
            position: relative;
            overflow: hidden;
            z-index: 1;
        }
        
        .btn-primary::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 0;
            height: 100%;
            background: var(--primary-color);
            z-index: -1;
            transition: width 0.3s ease;
        }
        
        .btn-primary:hover {
            color: #050819;
            transform: translateY(-2px);
            box-shadow: var(--neon-glow);
            background-color: transparent;
            border-color: var(--primary-color);
        }
        
        .btn-primary:hover::before {
            width: 100%;
        }
        
        #mindmap-container {
            width: 100%;
            height: 70vh;
            min-height: 500px;
            background: rgba(5, 10, 25, 0.75);
            border-radius: 14px;
            position: relative;
            overflow: auto;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
            display: none;
            z-index: 10;
            border: 1px solid var(--borders);
            background-image: 
                radial-gradient(circle at 10% 20%, rgba(0, 255, 238, 0.03) 0%, transparent 30%),
                radial-gradient(circle at 85% 60%, rgba(255, 42, 109, 0.03) 0%, transparent 30%);
            background-size: 150% 150%;
            background-position: 0% 0%;
            transition: all 0.5s ease;
            cursor: grab;
        }
        
        #mindmap-container:active {
            cursor: grabbing;
        }
        
        #mindmap-container:hover {
            background-position: 10% 20%;
            box-shadow: var(--shadow-neon);
        }
        
        #mindmap-container:hover::-webkit-scrollbar-thumb {
            background: var(--scrollbar-thumb-hover);
            box-shadow: var(--neon-glow);
        }
        
        .loading-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(5, 8, 25, 0.85);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 100;
            backdrop-filter: blur(5px);
            display: none;
            border-radius: 14px;
        }
        
        .spinner {
            width: 50px;
            height: 50px;
            border: 3px solid rgba(0, 255, 238, 0.1);
            border-radius: 50%;
            border-top-color: var(--primary-color);
            border-left-color: var(--primary-color);
            animation: spin 1s cubic-bezier(0.68, -0.55, 0.27, 1.55) infinite;
            filter: drop-shadow(0 0 8px rgba(0, 255, 238, 0.6));
        }
        
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        
        .navbar {
            background-color: rgba(5, 8, 25, 0.9);
            backdrop-filter: blur(10px);
            box-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
            border-bottom: 1px solid var(--borders);
            padding: 0.8rem 0;
        }
        
        .navbar-brand {
            color: var(--text-bright);
            font-weight: 700;
            letter-spacing: 1px;
            text-shadow: var(--text-glow);
        }
        
        .nav-link {
            color: rgba(242, 242, 247, 0.8);
            margin: 0 0.7rem;
            transition: all 0.3s;
            position: relative;
            padding: 0.5rem 0.2rem;
        }
        
        .nav-link::after {
            content: '';
            position: absolute;
            width: 0;
            height: 2px;
            bottom: 0;
            left: 0;
            background-color: var(--primary-color);
            transition: width 0.3s ease;
        }
        
        .nav-link:hover, .nav-link.active {
            color: var(--text-bright);
            text-shadow: var(--text-glow);
        }
        
        .nav-link:hover::after, .nav-link.active::after {
            width: 100%;
            box-shadow: var(--shadow-neon);
        }
        
        .user-info {
            background: rgba(0, 255, 238, 0.1);
            padding: 0.5rem 1.2rem;
            border-radius: 50px;
            color: var(--text-bright);
            display: none;
            border: 1px solid var(--borders);
            box-shadow: var(--shadow-neon);
        }
        
        .user-info i {
            margin-right: 0.5rem;
            color: var(--accent-color);
        }
        
        .alert-container {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 1000;
            max-width: 300px;
        }
        
        .alert-custom {
            background: var(--card-bg);
            color: var(--text-bright);
            border-left: 4px solid var(--accent-color);
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            backdrop-filter: blur(10px);
        }
        
        @media (max-width: 768px) {
            .upload-area {
                padding: 1.5rem 1rem;
            }
            
            .upload-container {
                padding: 1.2rem;
                margin-bottom: 1.5rem;
            }
            
            .header h1 {
                font-size: 1.8rem;
            }
            
            #mindmap-container {
                height: 60vh;
                min-height: 350px;
                touch-action: pan-x pan-y;
            }
            
            ::-webkit-scrollbar {
                width: 4px;
                height: 4px;
            }
            
            .feature-tip {
                width: 85%;
                left: 50%;
                transform: translateX(-50%) translateY(100px);
                font-size: 0.8rem;
                padding: 8px 12px;
            }
            
            .feature-tip.show {
                transform: translateX(-50%) translateY(0);
            }
            
            .drag-hint {
                font-size: 10px !important;
                padding: 3px 6px !important;
            }
        }
        
        #mindmap-container jmnode {
            background: linear-gradient(135deg, rgba(0, 255, 238, 0.8), rgba(0, 128, 255, 0.8)) !important;
            color: #050819 !important;
            box-shadow: 0 2px 10px rgba(0, 255, 238, 0.4);
            border-radius: 8px !important;
            padding: 6px 12px !important;
            font-family: 'Segoe UI', sans-serif !important;
            font-size: 14px !important;
            font-weight: 500 !important;
            transition: all 0.3s ease;
            border: 1px solid rgba(255, 255, 255, 0.2) !important;
        }
        
        #mindmap-container jmnode:hover {
            box-shadow: 0 0 15px rgba(0, 255, 238, 0.6);
            transform: translateY(-2px) scale(1.03);
            background: linear-gradient(135deg, rgba(0, 255, 238, 0.9), rgba(0, 128, 255, 0.9)) !important;
        }
        
        #mindmap-container jmexpander {
            background-color: rgba(0, 255, 238, 0.5) !important;
            box-shadow: 0 0 5px rgba(0, 255, 238, 0.3);
        }
        
        .jsmind-inner {
            background: transparent !important;
            position: relative;
            overflow: visible !important;
        }
        
        .error-msg {
            color: var(--accent-color);
            text-align: center;
            margin: 20px 0;
            font-weight: 500;
            display: none;
            text-shadow: 0 0 5px rgba(255, 42, 109, 0.5);
        }
        
        .action-controls {
            display: flex;
            justify-content: center;
            margin-top: 20px;
            gap: 15px;
        }
        
        .mind-map-controls {
            display: none;
            text-align: center;
            margin-bottom: 15px;
            animation: fadeIn 0.5s ease;
        }
        
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }
        
        .mind-map-controls button {
            margin: 0 5px;
            padding: 0.5rem 1.2rem;
            border-radius: 50px;
            background: rgba(0, 255, 238, 0.1);
            color: var(--primary-color);
            border: 1px solid var(--borders);
            transition: all 0.3s;
            position: relative;
            overflow: hidden;
            z-index: 1;
        }
        
        .mind-map-controls button::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 0;
            height: 100%;
            background: var(--primary-color);
            z-index: -1;
            transition: width 0.3s ease;
        }
        
        .mind-map-controls button:hover {
            color: #050819;
            transform: translateY(-2px);
            box-shadow: var(--neon-glow);
        }
        
        .mind-map-controls button:hover::before {
            width: 100%;
        }
        
        .download-btn {
            background: rgba(255, 42, 109, 0.2) !important;
            border-color: rgba(255, 42, 109, 0.3) !important;
            color: var(--accent-color) !important;
        }
        
        .download-btn:hover {
            color: #050819 !important;
        }
        
        .download-btn::before {
            background: var(--accent-color) !important;
        }
        
        .feature-tip {
            position: fixed;
            bottom: 20px;
            left: 20px;
            background: rgba(0, 255, 238, 0.1);
            backdrop-filter: blur(10px);
            padding: 12px 18px;
            border-radius: 8px;
            color: var(--text-light);
            font-size: 0.9rem;
            z-index: 1000;
            transform: translateY(100px);
            opacity: 0;
            transition: all 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
            box-shadow: var(--shadow-neon);
            border: 1px solid var(--borders);
        }
        
        .feature-tip.show {
            transform: translateY(0);
            opacity: 1;
        }
        
        .feature-tip .tip-close {
            position: absolute;
            top: 5px;
            right: 8px;
            color: rgba(242, 242, 247, 0.6);
            font-size: 16px;
            cursor: pointer;
            padding: 2px;
            transition: all 0.3s;
        }
        
        .feature-tip .tip-close:hover {
            color: var(--text-bright);
            text-shadow: var(--text-glow);
        }
        
        .drag-hint {
            background: rgba(0, 255, 238, 0.1) !important;
            border: 1px solid var(--borders) !important;
            box-shadow: var(--shadow-neon) !important;
        }
        
        .scroll-indicator {
            background: none !important;
            pointer-events: none !important;
        }
        
        .scroll-indicator-top {
            background: linear-gradient(to bottom, rgba(0, 255, 238, 0.2), transparent) !important;
        }
        
        .scroll-indicator-right {
            background: linear-gradient(to left, rgba(0, 255, 238, 0.2), transparent) !important;
        }
        
        .scroll-indicator-bottom {
            background: linear-gradient(to top, rgba(0, 255, 238, 0.2), transparent) !important;
        }
        
        .scroll-indicator-left {
            background: linear-gradient(to right, rgba(0, 255, 238, 0.2), transparent) !important;
        }
    </style>
</head>
<body>
    <h1 style="display: none;">EduBot - PPTX转思维导图</h1>
    <nav class="navbar navbar-expand-lg navbar-dark">
        <div class="container">
            <a class="navbar-brand" href="{{ front_end_domain_name }}/navigation_page">EduBot</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav me-auto">
                    <li class="nav-item">
                        <a class="nav-link" href="{{ front_end_domain_name }}/navigation_page">导航</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="{{ front_end_domain_name }}/video_processing_page">视频处理</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link active" href="{{ front_end_domain_name }}/pptx_generates_mind_maps_page">PPTX思维导图</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="{{ front_end_domain_name }}/ai_chat_page">小智</a>
                    </li>
                </ul>
                <div class="user-info" id="userInfoDisplay">
                    <i class="bi bi-person-circle"></i>
                    <span id="username"></span>
                </div>
                <a id="loginBtn" href="{{ front_end_domain_name }}/login_register_page" class="btn btn-primary ms-2">登录/注册</a>
            </div>
        </div>
    </nav>

    <div class="alert-container" id="alertContainer"></div>
    
    <div class="feature-tip" id="featureTip">
        <span>思维导图功能全面升级！体验流畅拖拽和缩放</span>
        <span class="tip-close" id="tipClose">×</span>
    </div>

    <div class="page-container">
        <div class="header">
            <h1>PPTX智能思维导图生成器</h1>
            <p>AI技术自动提取PPTX内容，构建结构化知识体系，让学习与教学更高效</p>
        </div>

        <div class="upload-container">
            <form id="uploadForm">
                <div class="upload-area" id="dropArea">
                    <div class="upload-icon">
                        <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" viewBox="0 0 16 16">
                            <path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
                            <path d="M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708l3-3z"/>
                        </svg>
                    </div>
                    <h5>上传PPTX文件</h5>
                    <p class="text-muted small mb-3">拖放或点击选择文件 (.pptx)</p>
                    <input type="file" id="fileInput" accept=".pptx" style="display: none;">
                    <button type="button" class="btn btn-primary" id="browseBtn">
                        选择文件
                    </button>
                </div>
            </form>
        </div>
        
        <div class="error-msg" id="errorMessage"></div>
        
        <div class="mind-map-controls" id="mindMapControls">
            <button id="saveMap" class="download-btn">保存思维导图</button>
        </div>

        <div id="mindmap-container">
            <div class="loading-overlay" id="loadingOverlay">
                <div class="spinner"></div>
            </div>
        </div>
        
        <div class="action-controls" id="actionControls" style="display:none">
            <button class="btn btn-primary" id="resetBtn">重新上传</button>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const backendDomainName = "{{ backend_domain_name }}";
            const frontEndDomainName = "{{ front_end_domain_name }}";
            const token = localStorage.getItem('token') || '';
            const fileInput = document.getElementById('fileInput');
            const browseBtn = document.getElementById('browseBtn');
            const dropArea = document.getElementById('dropArea');
            const mindmapContainer = document.getElementById('mindmap-container');
            let loadingOverlay = document.getElementById('loadingOverlay');
            const loginBtn = document.getElementById('loginBtn');
            const userInfoDisplay = document.getElementById('userInfoDisplay');
            const usernameElement = document.getElementById('username');
            const errorMessage = document.getElementById('errorMessage');
            const actionControls = document.getElementById('actionControls');
            const resetBtn = document.getElementById('resetBtn');
            const mindMapControls = document.getElementById('mindMapControls');
            const saveMapBtn = document.getElementById('saveMap');
            const featureTip = document.getElementById('featureTip');
            const tipClose = document.getElementById('tipClose');
            
            let mindmapInstance = null;
            let lastProcessedFile = null;
            let originalFileName = '';
            let globalPinchDistance = 0;
            let appState = {
                isProcessing: false,
                hasGeneratedMap: false,
                userAuthenticated: false,
                currentScale: 1
            };
            
            initializeApp();
            
            function initializeApp() {
                checkAuth();
                bindEventListeners();
                
                setTimeout(() => {
                    featureTip.classList.add('show');
                    
                    setTimeout(() => {
                        featureTip.classList.remove('show');
                    }, 6000);
                }, 1000);
            }
            
            function bindEventListeners() {
                browseBtn.addEventListener('click', () => fileInput.click());
                fileInput.addEventListener('change', handleFileSelect);
                resetBtn.addEventListener('click', resetUI);
                tipClose.addEventListener('click', () => featureTip.classList.remove('show'));
                
                saveMapBtn.addEventListener('click', () => {
                    if (mindmapInstance) {
                        saveMindMap();
                    } else {
                        showAlert('没有可保存的思维导图', 'warning');
                    }
                });
                
                setupDropEvents();
                
                window.addEventListener('resize', () => {
                    if (mindmapInstance && typeof mindmapInstance.resize === 'function') {
                        mindmapInstance.resize();
                    }
                });
            }
            
            function setupDropEvents() {
                dropArea.addEventListener('dragover', (e) => {
                    e.preventDefault();
                    dropArea.style.borderColor = 'var(--primary-color)';
                    dropArea.style.boxShadow = 'var(--neon-glow)';
                    dropArea.classList.add('pulse-glow');
                });
                
                dropArea.addEventListener('dragleave', (e) => {
                    e.preventDefault();
                    dropArea.style.borderColor = 'var(--borders)';
                    dropArea.style.boxShadow = 'none';
                    dropArea.classList.remove('pulse-glow');
                });
                
                dropArea.addEventListener('drop', (e) => {
                    e.preventDefault();
                    dropArea.style.borderColor = 'var(--borders)';
                    dropArea.style.boxShadow = 'none';
                    dropArea.classList.remove('pulse-glow');
                    
                    const files = e.dataTransfer.files;
                    if (files.length > 0) {
                        fileInput.files = files;
                        handleFileSelect({ target: fileInput });
                    }
                });
            }
            
            function pulseMindmapElement(action) {
                const container = document.getElementById('mindmap-container');
                
                if (!container) return;
                
                let pulseColor = 'rgba(0, 255, 238, 0.3)';
                if (action === 'zoom-out') {
                    pulseColor = 'rgba(255, 42, 109, 0.3)';
                }
                
                container.style.boxShadow = `0 0 30px ${pulseColor}`;
                
                setTimeout(() => {
                    container.style.boxShadow = '0 10px 25px rgba(0, 0, 0, 0.3)';
                }, 300);
            }
            
            async function checkAuth() {
                if (!token) {
                    window.location.href = frontEndDomainName + '/login_register_page';
                    return;
                }
                
                try {
                    const username = await checkTokenApi(backendDomainName, token);
                    if (username) {
                        loginBtn.style.display = 'none';
                        userInfoDisplay.style.display = 'inline-block';
                        usernameElement.textContent = username;
                        appState.userAuthenticated = true;
                    } else {
                        window.location.href = frontEndDomainName + '/login_register_page';
                    }
                } catch (error) {
                    console.error('身份验证失败:', error);
                    window.location.href = frontEndDomainName + '/login_register_page';
                }
            }
            
            function resetUI() {
                mindmapContainer.style.display = 'none';
                actionControls.style.display = 'none';
                mindMapControls.style.display = 'none';
                errorMessage.style.display = 'none';
                fileInput.value = '';
                lastProcessedFile = null;
                originalFileName = '';
                appState.hasGeneratedMap = false;
                
                document.querySelector('.upload-container').style.display = 'block';
                
                if (mindmapInstance) {
                    try {
                        mindmapInstance = null;
                    } catch(e) {}
                }
            }
            
            async function handleFileSelect(event) {
                const file = event.target.files[0];
                if (!file) return;
                
                if (appState.isProcessing) return;
                
                if (lastProcessedFile && lastProcessedFile.name === file.name && 
                    lastProcessedFile.size === file.size && 
                    lastProcessedFile.lastModified === file.lastModified) {
                    return;
                }
                
                lastProcessedFile = file;
                originalFileName = file.name.replace(/\.pptx$/i, '');
                
                if (!file.name.toLowerCase().endsWith('.pptx')) {
                    showError('请上传PPTX格式的文件');
                    return;
                }
                
                if (!token) {
                    showAlert('请先登录后再使用此功能', 'warning');
                    setTimeout(() => {
                        window.location.href = frontEndDomainName + '/login_register_page';
                    }, 2000);
                    return;
                }
                
                resetError();
                appState.isProcessing = true;
                
                try {
                    mindmapContainer.innerHTML = '<div class="loading-overlay" id="loadingOverlay"><div class="spinner"></div></div>';
                    loadingOverlay = document.getElementById('loadingOverlay');
                    loadingOverlay.style.display = 'flex';
                    mindmapContainer.style.display = 'block';
                    mindMapControls.style.display = 'none';
                    
                    document.querySelector('.upload-container').style.display = 'none';
                    
                    showAlert(`正在处理文件: ${file.name}`, 'info');
                    
                    const slideTexts = await extractPptxText(file);
                    if (!slideTexts || slideTexts.length <= 1) {
                        throw new Error('无法提取PPTX内容或PPTX内容为空');
                    }
                    
                    showAlert('正在生成思维导图，请稍候...', 'info');
                    
                    let mindmapData = await getPptxGeneratesMindMapsApi(
                        backendDomainName, 
                        token, 
                        JSON.stringify(slideTexts)
                    );
                    
                    if (typeof mindmapData === 'string') {
                        try {
                            mindmapData = JSON.parse(mindmapData);
                        } catch (e) {
                            throw new Error('思维导图数据格式错误');
                        }
                    }
                    
                    renderMindmap(mindmapData);
                    showControls();
                    showAlert('思维导图生成成功！', 'success');
                    appState.hasGeneratedMap = true;
                    
                } catch (error) {
                    showError(error.message || '处理失败，请重试');
                    mindmapContainer.style.display = 'none';
                    actionControls.style.display = 'flex';
                } finally {
                    if (loadingOverlay) {
                        loadingOverlay.style.display = 'none';
                    }
                    appState.isProcessing = false;
                }
            }
            
            function showError(message) {
                errorMessage.textContent = message;
                errorMessage.style.display = 'block';
                actionControls.style.display = 'flex';
                document.querySelector('.upload-container').style.display = 'block';
                showAlert(message, 'danger');
            }
            
            function resetError() {
                errorMessage.textContent = '';
                errorMessage.style.display = 'none';
            }
            
            function showControls() {
                actionControls.style.display = 'flex';
                mindMapControls.style.display = 'block';
            }
            
            function renderMindmap(data) {
                mindmapContainer.innerHTML = '';
                mindmapContainer.style.display = 'block';
                document.querySelector('.upload-container').style.display = 'none';
                
                if (typeof data === 'string') {
                    try {
                        data = JSON.parse(data);
                    } catch (e) {
                        showError('思维导图数据格式错误');
                        return;
                    }
                }
                
                try {
                    const rootId = data.id || "root";
                    const rootTopic = data.topic || "思维导图";
                    
                    const jsMindData = {
                        meta: {
                            name: "PPTX思维导图",
                            author: "AI教学评测系统",
                            version: "1.0"
                        },
                        format: "node_tree",
                        data: {
                            id: rootId,
                            topic: rootTopic,
                            children: transformToJsMindFormat(data.children || [])
                        }
                    };
                    
                    const options = {
                        container: 'mindmap-container',
                        editable: false,
                        theme: 'primary',
                        mode: 'full',
                        support_html: true,
                        view: {
                            hmargin: 100,
                            vmargin: 50,
                            line_width: 2,
                            line_color: 'rgba(0, 255, 238, 0.4)'
                        },
                        layout: {
                            hspace: 35,
                            vspace: 25,
                            pspace: 15
                        },
                        shortcut: {
                            enable: true,
                            handles: {},
                            mapping: {
                                zoomIn: [187, 107, 61], // +, numpad+, =
                                zoomOut: [189, 109, 173], // -, numpad-
                            }
                        }
                    };
                    
                    if (mindmapInstance) {
                        try {
                            mindmapInstance = null;
                        } catch(e) {}
                    }
                    
                    animateContainerEntry(mindmapContainer);
                    
                    window.setTimeout(() => {
                        mindmapInstance = new jsMind(options);
                        mindmapInstance.show(jsMindData);
                        
                        setupDraggableMap(mindmapContainer, mindmapInstance);
                        
                        window.setTimeout(() => {
                            if (mindmapInstance && typeof mindmapInstance.resize === 'function') {
                                mindmapInstance.resize();
                            }
                            
                            if (mindmapInstance && typeof mindmapInstance.view?.center_node === 'function' && 
                                typeof mindmapInstance.get_root === 'function') {
                                try {
                                    const rootNode = mindmapInstance.get_root();
                                    if (rootNode) {
                                        mindmapInstance.view.center_node(rootNode);
                                        animateNodes();
                                    }
                                } catch(e) {}
                            }
                            
                            addScrollIndicators(mindmapContainer);
                        }, 300);
                    }, 100);
                    
                } catch (error) {
                    showError('思维导图渲染失败: ' + error.message);
                }
            }
            
            function animateContainerEntry(container) {
                if (!container) return;
                
                container.style.opacity = '0';
                container.style.transform = 'translateY(20px)';
                
                setTimeout(() => {
                    container.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
                    container.style.opacity = '1';
                    container.style.transform = 'translateY(0)';
                }, 50);
            }
            
            function animateNodes() {
                const nodes = document.querySelectorAll('jmnode');
                nodes.forEach((node, index) => {
                    node.style.opacity = '0';
                    node.style.transform = 'scale(0.8)';
                    node.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
                    
                    setTimeout(() => {
                        node.style.opacity = '1';
                        node.style.transform = 'scale(1)';
                    }, 100 + index * 30);
                });
            }
            
            function setupDraggableMap(container, instance) {
                if (!container || !instance) return;
                
                let isDragging = false;
                let lastX, lastY;
                let touchDevice = false;
                let lastPinchDistance = 0;
                
                function isTouchDevice() {
                    return ('ontouchstart' in window) ||
                        (navigator.maxTouchPoints > 0) ||
                        (navigator.msMaxTouchPoints > 0);
                }
                
                const dragHint = document.createElement('div');
                dragHint.className = 'drag-hint';
                
                if (isTouchDevice()) {
                    touchDevice = true;
                    dragHint.textContent = '单指拖动平移，双指可缩放';
                } else {
                    dragHint.textContent = '鼠标左键拖动平移，滚轮缩放';
                }
                
                dragHint.style.position = 'absolute';
                dragHint.style.bottom = '15px';
                dragHint.style.right = '15px';
                dragHint.style.background = 'rgba(0, 0, 0, 0.6)';
                dragHint.style.color = 'var(--text-light)';
                dragHint.style.padding = '5px 10px';
                dragHint.style.borderRadius = '8px';
                dragHint.style.fontSize = '12px';
                dragHint.style.opacity = '0';
                dragHint.style.pointerEvents = 'none';
                dragHint.style.zIndex = '100';
                dragHint.style.transition = 'opacity 0.5s ease';
                container.appendChild(dragHint);
                
                setTimeout(() => {
                    dragHint.style.opacity = '0.9';
                    
                    setTimeout(() => {
                        dragHint.style.opacity = '0';
                        setTimeout(() => {
                            try {
                                container.removeChild(dragHint);
                            } catch(e) {}
                        }, 500);
                    }, 5000);
                }, 1000);
                
                if (touchDevice) {
                    container.style.cursor = 'default';
                    
                    container.addEventListener('touchstart', handleTouchStart, { passive: false });
                    document.addEventListener('touchmove', handleTouchMove, { passive: false });
                    document.addEventListener('touchend', handleTouchEnd);
                } else {
                    container.addEventListener('mousedown', startDrag);
                    document.addEventListener('mousemove', drag);
                    document.addEventListener('mouseup', endDrag);
                    
                    container.addEventListener('wheel', handleWheel, { passive: false });
                }
                
                function startDrag(e) {
                    if (e.button === 0 && instance?.view) {
                        isDragging = true;
                        lastX = e.clientX;
                        lastY = e.clientY;
                        container.style.cursor = 'grabbing';
                        e.preventDefault();
                    }
                }
                
                function drag(e) {
                    if (!isDragging) return;
                    
                    const dx = e.clientX - lastX;
                    const dy = e.clientY - lastY;
                    lastX = e.clientX;
                    lastY = e.clientY;
                    
                    container.scrollLeft -= dx;
                    container.scrollTop -= dy;
                    e.preventDefault();
                    
                    updateScrollIndicators(container);
                }
                
                function endDrag() {
                    if (isDragging) {
                        isDragging = false;
                        container.style.cursor = 'grab';
                    }
                }
                
                function handleTouchStart(e) {
                    if (e.touches.length === 1) {
                        touchDevice = true;
                        isDragging = true;
                        lastX = e.touches[0].clientX;
                        lastY = e.touches[0].clientY;
                    } else if (e.touches.length === 2 && instance?.view?.zoom_in && instance?.view?.zoom_out) {
                        e.preventDefault();
                        
                        const touch1 = e.touches[0];
                        const touch2 = e.touches[1];
                        lastPinchDistance = Math.hypot(
                            touch2.clientX - touch1.clientX,
                            touch2.clientY - touch1.clientY
                        );
                    }
                }
                
                function handleTouchMove(e) {
                    if (!isDragging) return;
                    
                    if (e.touches.length === 1) {
                        const dx = e.touches[0].clientX - lastX;
                        const dy = e.touches[0].clientY - lastY;
                        lastX = e.touches[0].clientX;
                        lastY = e.touches[0].clientY;
                        
                        container.scrollLeft -= dx;
                        container.scrollTop -= dy;
                        e.preventDefault();
                    } else if (e.touches.length === 2 && instance?.view?.zoom_in && instance?.view?.zoom_out) {
                        e.preventDefault();
                        
                        const touch1 = e.touches[0];
                        const touch2 = e.touches[1];
                        const currentPinchDistance = Math.hypot(
                            touch2.clientX - touch1.clientX,
                            touch2.clientY - touch1.clientY
                        );
                        
                        if (lastPinchDistance && currentPinchDistance) {
                            if (currentPinchDistance - lastPinchDistance > 5) {
                                instance.view.zoom_in();
                                lastPinchDistance = currentPinchDistance;
                                container.style.boxShadow = '0 0 20px rgba(0, 255, 238, 0.5)';
                                setTimeout(() => {
                                    container.style.boxShadow = '0 10px 25px rgba(0, 0, 0, 0.3)';
                                }, 300);
                            } else if (lastPinchDistance - currentPinchDistance > 5) {
                                instance.view.zoom_out();
                                lastPinchDistance = currentPinchDistance;
                                container.style.boxShadow = '0 0 20px rgba(255, 42, 109, 0.5)';
                                setTimeout(() => {
                                    container.style.boxShadow = '0 10px 25px rgba(0, 0, 0, 0.3)';
                                }, 300);
                            }
                        }
                    }
                    
                    updateScrollIndicators(container);
                }
                
                function handleTouchEnd() {
                    isDragging = false;
                    lastPinchDistance = 0;
                    container.style.boxShadow = '0 10px 25px rgba(0, 0, 0, 0.3)';
                    updateScrollIndicators(container);
                }
                
                function handleWheel(e) {
                    if (instance?.view) {
                        e.preventDefault();
                        if (e.deltaY < 0) {
                            instance.view.zoom_in && instance.view.zoom_in();
                            container.style.boxShadow = '0 0 20px rgba(0, 255, 238, 0.5)';
                        } else {
                            instance.view.zoom_out && instance.view.zoom_out();
                            container.style.boxShadow = '0 0 20px rgba(255, 42, 109, 0.5)';
                        }
                        
                        setTimeout(() => {
                            container.style.boxShadow = '0 10px 25px rgba(0, 0, 0, 0.3)';
                        }, 300);
                    }
                }
                
                container._draggableState = {
                    instance,
                    touchDevice
                };
            }
            
            function addScrollIndicators(container) {
                if (!container) return;
                
                const oldIndicators = container.querySelectorAll('.scroll-indicator');
                oldIndicators.forEach(indicator => indicator.remove());
                
                const directions = ['top', 'right', 'bottom', 'left'];
                directions.forEach(direction => {
                    const indicator = document.createElement('div');
                    indicator.className = `scroll-indicator scroll-indicator-${direction}`;
                    indicator.style.position = 'absolute';
                    indicator.style.pointerEvents = 'none';
                    indicator.style.opacity = '0';
                    indicator.style.transition = 'opacity 0.3s ease';
                    indicator.style.zIndex = '50';
                    
                    switch(direction) {
                        case 'top':
                            indicator.style.top = '0';
                            indicator.style.left = '0';
                            indicator.style.right = '0';
                            indicator.style.height = '30px';
                            break;
                        case 'right':
                            indicator.style.top = '0';
                            indicator.style.right = '0';
                            indicator.style.bottom = '0';
                            indicator.style.width = '30px';
                            break;
                        case 'bottom':
                            indicator.style.bottom = '0';
                            indicator.style.left = '0';
                            indicator.style.right = '0';
                            indicator.style.height = '30px';
                            break;
                        case 'left':
                            indicator.style.top = '0';
                            indicator.style.left = '0';
                            indicator.style.bottom = '0';
                            indicator.style.width = '30px';
                            break;
                    }
                    
                    container.appendChild(indicator);
                });
                
                updateScrollIndicators(container);
                container.addEventListener('scroll', () => updateScrollIndicators(container));
            }
            
            function updateScrollIndicators(container) {
                if (!container) return;
                
                const topIndicator = container.querySelector('.scroll-indicator-top');
                const rightIndicator = container.querySelector('.scroll-indicator-right');
                const bottomIndicator = container.querySelector('.scroll-indicator-bottom');
                const leftIndicator = container.querySelector('.scroll-indicator-left');
                
                if (topIndicator) {
                    topIndicator.style.opacity = container.scrollTop > 10 ? '1' : '0';
                }
                
                if (rightIndicator) {
                    rightIndicator.style.opacity = container.scrollLeft < (container.scrollWidth - container.clientWidth - 10) ? '1' : '0';
                }
                
                if (bottomIndicator) {
                    bottomIndicator.style.opacity = container.scrollTop < (container.scrollHeight - container.clientHeight - 10) ? '1' : '0';
                }
                
                if (leftIndicator) {
                    leftIndicator.style.opacity = container.scrollLeft > 10 ? '1' : '0';
                }
            }
            
            function transformToJsMindFormat(children) {
                if (!Array.isArray(children)) {
                    return [];
                }
                
                return children.map((child, index) => {
                    const nodeId = child.id || ("node_" + Date.now() + "_" + index);
                    return {
                        id: nodeId,
                        topic: child.topic || "未命名节点",
                        children: Array.isArray(child.children) ? transformToJsMindFormat(child.children) : []
                    };
                });
            }
            
            function showAlert(message, type) {
                const alertContainer = document.getElementById('alertContainer');
                const alert = document.createElement('div');
                
                alert.className = `alert alert-custom alert-${type} alert-dismissible fade show`;
                alert.innerHTML = `
                    ${message}
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                `;
                
                alertContainer.appendChild(alert);
                
                setTimeout(() => {
                    alert.style.opacity = '0';
                    alert.style.transform = 'translateY(-10px)';
                    alert.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
                    
                    setTimeout(() => {
                        alertContainer.removeChild(alert);
                    }, 300);
                }, 4000);
            }
            
            function saveMindMap() {
                if (!mindmapInstance) {
                    showAlert('没有可保存的思维导图', 'warning');
                    return;
                }
                
                try {
                    loadingOverlay.style.display = 'flex';
                    showAlert('正在处理思维导图，请稍候...', 'info');
                    
                    const mindMapData = mindmapInstance.get_data();
                    
                    const tempContainer = document.createElement('div');
                    tempContainer.id = 'temp-mindmap-container';
                    tempContainer.style.position = 'absolute';
                    tempContainer.style.left = '-9999px';
                    tempContainer.style.top = '-9999px';
                    tempContainer.style.width = '2000px';
                    tempContainer.style.height = '2000px';
                    tempContainer.style.backgroundColor = 'var(--bg-dark)';
                    document.body.appendChild(tempContainer);
                    
                    const exportOptions = {
                        container: 'temp-mindmap-container',
                        editable: false,
                        theme: 'primary',
                        mode: 'full',
                        support_html: true,
                        view: {
                            hmargin: 50,
                            vmargin: 50,
                            line_width: 2,
                            line_color: 'rgba(0, 255, 238, 0.4)'
                        },
                        layout: {
                            hspace: 30,
                            vspace: 20,
                            pspace: 13
                        }
                    };
                    
                    setTimeout(() => {
                        try {
                            if (typeof html2canvas !== 'function') {
                                const script = document.createElement('script');
                                script.src = 'https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js';
                                script.onload = () => {
                                    renderExportMindmap(tempContainer, mindMapData, exportOptions);
                                };
                                script.onerror = () => {
                                    cleanup(tempContainer);
                                    loadingOverlay.style.display = 'none';
                                    showAlert('无法加载html2canvas库', 'danger');
                                };
                                document.head.appendChild(script);
                            } else {
                                renderExportMindmap(tempContainer, mindMapData, exportOptions);
                            }
                        } catch (error) {
                            cleanup(tempContainer);
                            loadingOverlay.style.display = 'none';
                            showAlert('准备导出思维导图失败: ' + error.message, 'danger');
                        }
                    }, 100);
                } catch (error) {
                    loadingOverlay.style.display = 'none';
                    showAlert('保存思维导图失败: ' + error.message, 'danger');
                }
            }
            
            function renderExportMindmap(container, data, options) {
                try {
                    const exportInstance = new jsMind(options);
                    exportInstance.show(data);
                    
                    setTimeout(() => {
                        try {
                            const nodes = container.querySelectorAll('jmnode');
                            if (nodes.length === 0) {
                                throw new Error('临时思维导图渲染失败');
                            }
                            
                            if (exportInstance.view && typeof exportInstance.view.set_scale === 'function') {
                                exportInstance.view.set_scale(1);
                            }
                            
                            exportAsImage(container);
                        } catch (error) {
                            cleanup(container);
                            loadingOverlay.style.display = 'none';
                            showAlert('临时思维导图渲染失败: ' + error.message, 'danger');
                        }
                    }, 500);
                } catch (error) {
                    cleanup(container);
                    loadingOverlay.style.display = 'none';
                    showAlert('创建导出实例失败: ' + error.message, 'danger');
                }
            }
            
            function exportAsImage(container) {
                try {
                    const nodes = container.querySelectorAll('jmnode');
                    let minX = Number.MAX_SAFE_INTEGER;
                    let minY = Number.MAX_SAFE_INTEGER;
                    let maxX = 0;
                    let maxY = 0;
                    
                    const nodePositions = [];
                    nodes.forEach(node => {
                        const rect = node.getBoundingClientRect();
                        const containerRect = container.getBoundingClientRect();
                        
                        const relX = rect.left - containerRect.left + container.scrollLeft;
                        const relY = rect.top - containerRect.top + container.scrollTop;
                        
                        nodePositions.push({
                            x: relX,
                            y: relY,
                            width: rect.width,
                            height: rect.height
                        });
                        
                        minX = Math.min(minX, relX);
                        minY = Math.min(minY, relY);
                        maxX = Math.max(maxX, relX + rect.width);
                        maxY = Math.max(maxY, relY + rect.height);
                    });
                    
                    const lines = container.querySelectorAll('jmexpander, path');
                    lines.forEach(line => {
                        const rect = line.getBoundingClientRect();
                        const containerRect = container.getBoundingClientRect();
                        
                        const relX = rect.left - containerRect.left + container.scrollLeft;
                        const relY = rect.top - containerRect.top + container.scrollTop;
                        
                        minX = Math.min(minX, relX);
                        minY = Math.min(minY, relY);
                        maxX = Math.max(maxX, relX + rect.width);
                        maxY = Math.max(maxY, relY + rect.height);
                    });
                    
                    if (minX === Number.MAX_SAFE_INTEGER) {
                        minX = 0;
                        minY = 0;
                        maxX = 800;
                        maxY = 600;
                    }
                    
                    const contentWidth = maxX - minX;
                    const contentHeight = maxY - minY;
                    
                    const paddingRatio = 0.05;
                    const paddingX = Math.max(20, Math.min(50, contentWidth * paddingRatio));
                    const paddingY = Math.max(20, Math.min(50, contentHeight * paddingRatio));
                    
                    minX = Math.max(0, minX - paddingX);
                    minY = Math.max(0, minY - paddingY);
                    maxX = maxX + paddingX;
                    maxY = maxY + paddingY;
                    
                    const minWidth = 300;
                    const minHeight = 200;
                    if (maxX - minX < minWidth) maxX = minX + minWidth;
                    if (maxY - minY < minHeight) maxY = minY + minHeight;
                    
                    const captureWidth = Math.min(maxX - minX, 3000);
                    const captureHeight = Math.min(maxY - minY, 3000);
                    
                    container.style.width = (captureWidth + 50) + 'px';
                    container.style.height = (captureHeight + 50) + 'px';
                    
                    const canvasOptions = {
                        backgroundColor: '#050819',
                        scale: 2,
                        logging: false,
                        allowTaint: true,
                        useCORS: true,
                        x: minX,
                        y: minY,
                        width: captureWidth,
                        height: captureHeight,
                        scrollX: 0,
                        scrollY: 0,
                        windowWidth: container.scrollWidth,
                        windowHeight: container.scrollHeight
                    };
                    
                    setTimeout(() => {
                        html2canvas(container, canvasOptions).then(canvas => {
                            try {
                                const trimmedCanvas = trimCanvas(canvas);
                                
                                let finalCanvas = trimmedCanvas;
                                if (finalCanvas.width > 5000 || finalCanvas.height > 5000) {
                                    const scaleFactor = Math.min(5000 / finalCanvas.width, 5000 / finalCanvas.height);
                                    const scaledCanvas = document.createElement('canvas');
                                    scaledCanvas.width = finalCanvas.width * scaleFactor;
                                    scaledCanvas.height = finalCanvas.height * scaleFactor;
                                    
                                    const ctx = scaledCanvas.getContext('2d');
                                    ctx.drawImage(finalCanvas, 0, 0, scaledCanvas.width, scaledCanvas.height);
                                    finalCanvas = scaledCanvas;
                                }
                                
                                const imageUrl = finalCanvas.toDataURL('image/png', 0.9);
                                
                                const downloadLink = document.createElement('a');
                                downloadLink.href = imageUrl;
                                
                                const fileName = `${originalFileName || 'pptx'}_思维导图.png`;
                                downloadLink.download = fileName;
                                
                                document.body.appendChild(downloadLink);
                                downloadLink.click();
                                document.body.removeChild(downloadLink);
                                
                                showAlert(`思维导图已保存为: ${fileName}`, 'success');
                            } catch (error) {
                                showAlert('图片转换失败: ' + error.message, 'danger');
                            } finally {
                                cleanup(container);
                                loadingOverlay.style.display = 'none';
                            }
                        }).catch(error => {
                            cleanup(container);
                            loadingOverlay.style.display = 'none';
                            showAlert('Canvas转换失败: ' + error.message, 'danger');
                        });
                    }, 100);
                } catch (error) {
                    cleanup(container);
                    loadingOverlay.style.display = 'none';
                    showAlert('导出过程中出错: ' + error.message, 'danger');
                }
            }
            
            function trimCanvas(canvas) {
                const context = canvas.getContext('2d');
                const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
                const data = imageData.data;
                
                let leftEdge = canvas.width;
                let rightEdge = 0;
                let topEdge = canvas.height;
                let bottomEdge = 0;
                
                const bgColor = { r: 5, g: 8, b: 25 };
                const tolerance = 15;
                
                for (let y = 0; y < canvas.height; y++) {
                    for (let x = 0; x < canvas.width; x++) {
                        const index = (y * canvas.width + x) * 4;
                        const r = data[index];
                        const g = data[index + 1];
                        const b = data[index + 2];
                        const a = data[index + 3];
                        
                        if (a > 0 && (
                            Math.abs(r - bgColor.r) > tolerance ||
                            Math.abs(g - bgColor.g) > tolerance ||
                            Math.abs(b - bgColor.b) > tolerance
                        )) {
                            if (x < leftEdge) leftEdge = x;
                            if (x > rightEdge) rightEdge = x;
                            if (y < topEdge) topEdge = y;
                            if (y > bottomEdge) bottomEdge = y;
                        }
                    }
                }
                
                if (rightEdge < leftEdge) rightEdge = leftEdge;
                if (bottomEdge < topEdge) bottomEdge = topEdge;
                
                const padding = 15;
                leftEdge = Math.max(0, leftEdge - padding);
                topEdge = Math.max(0, topEdge - padding);
                rightEdge = Math.min(canvas.width - 1, rightEdge + padding);
                bottomEdge = Math.min(canvas.height - 1, bottomEdge + padding);
                
                const trimWidth = rightEdge - leftEdge + 1;
                const trimHeight = bottomEdge - topEdge + 1;
                
                const trimmedCanvas = document.createElement('canvas');
                trimmedCanvas.width = trimWidth;
                trimmedCanvas.height = trimHeight;
                
                const trimmedContext = trimmedCanvas.getContext('2d');
                trimmedContext.fillStyle = '#050819';
                trimmedContext.fillRect(0, 0, trimWidth, trimHeight);
                trimmedContext.drawImage(
                    canvas,
                    leftEdge, topEdge, trimWidth, trimHeight,
                    0, 0, trimWidth, trimHeight
                );
                
                return trimmedCanvas;
            }
            
            function cleanup(container) {
                try {
                    if (container && container.parentNode) {
                        container.parentNode.removeChild(container);
                    }
                } catch (e) {}
            }
        });
    </script>
</body>
</html>
